package cn.com.chengmandian.bike.controller.rent;


import cn.com.chengmandian.agent.utils.AuthUtil;
import cn.com.chengmandian.agent.utils.ServletUtil;
import cn.com.chengmandian.bike.dto.MemberRentComboBuyForm;
import cn.com.chengmandian.bike.model.*;
import cn.com.chengmandian.bike.model.vo.RentOrderVo;
import cn.com.chengmandian.bike.service.*;
import cn.com.chengmandian.bike.utils.AliPayUtil;
import cn.com.chengmandian.bike.utils.WxPayUtil;
import cn.com.chengmandian.core.redis.cache.AgentParamCacheService;
import cn.com.chengmandian.core.web.exceptions.BadResponseException;
import cn.com.chengmandian.core.web.pojo.AgentInfo;
import cn.com.chengmandian.core.web.pojo.AjaxResult;
import cn.com.chengmandian.core.web.pojo.BikeAreaParam;
import cn.com.chengmandian.core.web.utils.LocalMapUtil;
import cn.com.chengmandian.service.bike.BikePayClient;
import cn.com.chengmandian.service.bike.constants.ChannelTypeEnum;
import cn.com.chengmandian.service.bike.constants.MemberPayBusinessTypeEnum;
import cn.com.chengmandian.service.bike.constants.PayChannelEnum;
import cn.com.chengmandian.service.bike.form.BikePayForm;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * <p>
 * 电单车运营-分时租赁-套餐信息 前端控制器
 * </p>
 *
 * @author AutoGenerator
 * @since 2023-07-10
 */
@Api(tags = "分时租赁-套餐信息")
@RestController
@RequestMapping("/rent/combo")
public class EbRentComboController {

    @Autowired
    private IEbRentComboService rentComboService;
    @Autowired
    private IEbMemberWalletService memberWalletService;
    @Autowired
    private IEbRentOrderService rentOrderService;
    @Autowired
    private IEbMemberInfoService memberInfoService;
    @Autowired
    private IEbMemberPayService memberPayService;
    @Autowired
    private IEbRentPenaltyService rentPenaltyService;
    @Autowired
    private AgentParamCacheService agentParamCacheService;

    @Autowired
    private IEbAgentInfoService agentInfoService;

    @Autowired
    private IEbPayAccountService payAccountService;

    @Autowired
    private BikePayClient payClient;

    @ApiOperation("用户可购买套餐(无需登录)")
    @PostMapping("/buy/enable")
    public AjaxResult<List<EbRentCombo>> enable(){
        AgentInfo agentInfo = LocalMapUtil.getAgentInfo();
        Assert.notNull(agentInfo.getAreaId(), "缺少运营区id");
        return AjaxResult.success(rentComboService.enable(agentInfo.getAreaId()));
    }

    @ApiOperation("详情")
    @GetMapping("/detail/{id}")
    public AjaxResult<EbRentCombo> detail(@PathVariable("id") Integer id){
        return AjaxResult.success(rentComboService.detail(id));
    }

    @ApiOperation("购买租赁套餐(非续租)")
    @PostMapping("/buy")
    public AjaxResult buy(@RequestBody MemberRentComboBuyForm form) throws Exception{
        Assert.notNull(form.getComboId(), "请选择租赁套餐");
        Assert.notNull(form.getPayChannel(), "请选择充值渠道");

        EbRentCombo rentCombo = rentComboService.detail(form.getComboId());
        Assert.notNull(rentCombo, "不存在的租赁套餐");

        BikeAreaParam bikeAreaParam = agentParamCacheService.getParam(rentCombo.getAgentId(), rentCombo.getAreaId());
        Assert.isTrue(bikeAreaParam != null && bikeAreaParam.getUserRideRentEnable(), "分时租赁未开启");
        if(ObjectUtil.isNotNull(bikeAreaParam) && ObjectUtil.isNotNull(bikeAreaParam.getUserRideEnable()) && !bikeAreaParam.getUserRideEnable()){
            throw new BadResponseException(514,bikeAreaParam.getUserRideStopNote());
        }

        Integer memberId = AuthUtil.getAgentUser().getId();
        EbRentOrder rentOrders = rentOrderService.getComboRent(memberId);
        Assert.isNull(rentOrders, "存在租赁中订单，暂不支持购买");

        RentOrderVo runningRentOrders = rentOrderService.getComboRunning(memberId);
        Assert.isNull(runningRentOrders, "存在进行中订单，暂不支持购买");

        if (form.getPayChannel().equals(PayChannelEnum.WALLET.getCode())) {
            EbMemberWallet memberWallet = memberWalletService.getMemberWallet(memberId);
            if (memberWallet.getChargeMoney().compareTo(rentCombo.getPrice()) < 0) {
                return AjaxResult.error("钱包充值余额不足");
            }
        }
        AgentInfo agentInfo = LocalMapUtil.getAgentInfo();
        EbMemberInfo memberInfo = memberInfoService.getById(memberId);

        EbAgentInfo info = agentInfoService.getById(agentInfo.getId());
        if (info.getPayAccountId() != null) {
            EbPayAccount payAccount = payAccountService.getPayAccount(info.getPayAccountId(), memberId);
            if (payAccount != null && (form.getPayChannel().equals(PayChannelEnum.WXPAY.getCode()) || form.getPayChannel().equals(PayChannelEnum.ALIPAY.getCode()))) {
                PayChannelEnum payChannel = PayChannelEnum.getByCode(form.getPayChannel());
                BikePayForm bikePayForm = new BikePayForm();
                bikePayForm.setPayBusinessType(MemberPayBusinessTypeEnum.RENT_ORDER_PAY);
                bikePayForm.setPayChannel(payChannel);
                bikePayForm.setMoney(rentCombo.getPrice());
                bikePayForm.setOpenId(StrUtil.isNotBlank(form.getOpenId()) ? form.getOpenId() : memberInfo.getOpenId());
                bikePayForm.setAlipayUserId(memberInfo.getAlipayUserId());
                bikePayForm.setAlipayOpenId(memberInfo.getAlipayOpenId());
                bikePayForm.setAreaId(agentInfo.getAreaId());
                bikePayForm.setMemberId(AuthUtil.getAgentUser().getId());
                bikePayForm.setBusinessId(rentCombo.getId());
                bikePayForm.setClientIp(ServletUtil.getIp());
                return payClient.pay(agentInfo.getId(), bikePayForm);
            }
        }

        EbMemberPay memberPay = memberPayService.createPay(rentCombo.getAreaId(), memberInfo.getId(), MemberPayBusinessTypeEnum.RENT_ORDER_PAY, rentCombo.getId(),
                rentCombo.getPrice(), form.getPayChannel());


        String notifyUrl = "http://"+ agentInfo.getDomain() + "/api/v1/bikeuser/notify/rent";

        if (form.getPayChannel().equals(PayChannelEnum.WXPAY.getCode())) {
            Assert.isTrue(StrUtil.isNotBlank(agentInfo.getWxMchId()), "未开启微信支付");
            if (form.getChannelType().equals(ChannelTypeEnum.MINI.getCode())) {
                String openId = StrUtil.isNotBlank(form.getOpenId()) ? form.getOpenId() : memberInfo.getOpenId();
                Assert.isTrue(StrUtil.isNotBlank(openId), "缺少openid");
                return AjaxResult.success(WxPayUtil.jsapiTransactions(
                        agentInfo.getWxMiniAppid(),
                        agentInfo.getWxMchId(),
                        openId,
                        "用户购买租赁套餐",
                        memberPay.getPayNo(),
                        memberPay.getMoney(),
                        agentInfo.getWxKeyPath(),
                        agentInfo.getWxCertPath(),
                        notifyUrl + "/wxpay/pay/" + LocalMapUtil.getAgentInfo().getId()
                ));
            }
        } else if (form.getPayChannel().equals(PayChannelEnum.ALIPAY.getCode())) {
            // 支付宝用户唯一标识user_id 和open_id必须有一个有值
            Assert.isTrue(StrUtil.isNotBlank(memberInfo.getAlipayUserId()) || StrUtil.isNotBlank(memberInfo.getAlipayOpenId()), "用户缺少支付宝用户标识");
            return AjaxResult.success(AliPayUtil.getTradeCreateRequestParam(
                    agentInfo.getAliMiniAppid(),
                    memberInfo.getAlipayUserId(),
                    memberInfo.getAlipayOpenId(),
                    "用户购买租赁套餐",
                    memberPay.getPayNo(),
                    memberPay.getMoney(),
                    agentInfo.getAliPayPrivateKey(),
                    agentInfo.getAliPayCertPath(),
                    agentInfo.getAliPayPublicCertPath(),
                    agentInfo.getAliPayRootCertPath(),
                    notifyUrl + "/ali/pay/" + LocalMapUtil.getAgentInfo().getId()
            ));
        } else if (form.getPayChannel().equals(PayChannelEnum.WALLET.getCode())) {
            rentOrderService.rentOrderPaySuccess(memberPay.getPayNo(), null);
            return AjaxResult.success("购买成功");
        }
        return AjaxResult.error("不支持的支付方式！");
    }
}
